D:\git\skunkworks\herald-for-cpp\herald-tests\coordinator-tests.cpp
Line | Count | Source |
1 | | // Copyright 2021 Herald Project Contributors |
2 | | // SPDX-License-Identifier: Apache-2.0 |
3 | | // |
4 | | |
5 | | #include <memory> |
6 | | #include <vector> |
7 | | #include <optional> |
8 | | #include <iostream> |
9 | | |
10 | | #include "test-templates.h" |
11 | | |
12 | | #include "catch.hpp" |
13 | | |
14 | | #include "herald/herald.h" |
15 | | |
16 | | /** |
17 | | * This set of tests uses the BLECoordinator and a Mock Herald V1 Protocol provider |
18 | | * to test the iteration functionality of the core Coordinator class |
19 | | */ |
20 | | |
21 | | template <typename CoordProvT> |
22 | | class MockSensor { |
23 | | public: |
24 | 1 | MockSensor(CoordProvT& provider) : cp(provider) {} |
25 | | ~MockSensor() = default; |
26 | | |
27 | | void start() {} |
28 | | void stop() {} |
29 | | |
30 | | /** For complex sensor coordination support, if required - Since v1.2-beta3 **/ |
31 | 1 | std::optional<std::reference_wrapper<herald::engine::CoordinationProvider>> coordinationProvider() { |
32 | 1 | return std::optional<std::reference_wrapper<herald::engine::CoordinationProvider>>(cp); |
33 | 1 | } |
34 | | |
35 | | CoordProvT& cp; |
36 | | }; |
37 | | |
38 | | template <typename ContextT, typename BLEDBT> |
39 | | class NoOpHeraldV1ProtocolProvider : public herald::ble::HeraldProtocolV1Provider { |
40 | | public: |
41 | | NoOpHeraldV1ProtocolProvider(ContextT& context,BLEDBT& bledb) |
42 | | : ctx(context) |
43 | | HLOGGERINIT(ctx,"TESTS","NoOpProvider") |
44 | | {} |
45 | | ~NoOpHeraldV1ProtocolProvider() = default; |
46 | | |
47 | | // FOR PLATFORMS WITH STD::ASYNC:- |
48 | | // void openConnection(const herald::datatype::TargetIdentifier& toTarget, |
49 | | // const herald::ble::HeraldConnectionCallback& connCallback) override { |
50 | | // connCallback(toTarget, true); |
51 | | // } |
52 | | |
53 | | // void closeConnection(const herald::datatype::TargetIdentifier& toTarget, |
54 | | // const herald::ble::HeraldConnectionCallback& connCallback) override { |
55 | | // connCallback(toTarget,false); |
56 | | // } |
57 | | |
58 | | // void serviceDiscovery(herald::engine::Activity act, herald::engine::CompletionCallback cb) override { |
59 | | // HTDBG("serviceDiscovery called"); |
60 | | // cb(act,{}); |
61 | | // } |
62 | | |
63 | | // void readPayload(herald::engine::Activity act, herald::engine::CompletionCallback cb) override { |
64 | | // HTDBG("readPayload called"); |
65 | | // cb(act,{}); |
66 | | // } |
67 | | |
68 | | // void immediateSend(herald::engine::Activity act, herald::engine::CompletionCallback cb) override { |
69 | | // HTDBG("immediateSend called"); |
70 | | // cb(act,{}); |
71 | | // } |
72 | | |
73 | | // void immediateSendAll(herald::engine::Activity act, herald::engine::CompletionCallback cb) override { |
74 | | // HTDBG("immediateSendAll called"); |
75 | | // cb(act,{}); |
76 | | // } |
77 | | |
78 | | // FOR PLATFORMS WITHOUT STD::SYNC |
79 | | bool openConnection(const herald::datatype::TargetIdentifier& toTarget) override { |
80 | | return true; |
81 | | } |
82 | | bool closeConnection(const herald::datatype::TargetIdentifier& toTarget) override { |
83 | | return false; |
84 | | } |
85 | | |
86 | | void restartScanningAndAdvertising() override {} |
87 | | |
88 | | std::optional<herald::engine::Activity> serviceDiscovery(herald::engine::Activity act) override { |
89 | | HTDBG("serviceDiscovery called"); |
90 | | return {}; |
91 | | } |
92 | | |
93 | | std::optional<herald::engine::Activity> readPayload(herald::engine::Activity act) override { |
94 | | HTDBG("readPayload called"); |
95 | | return {}; |
96 | | } |
97 | | |
98 | | // std::optional<herald::engine::Activity> immediateSend(herald::engine::Activity act) override { |
99 | | // HTDBG("immediateSend called"); |
100 | | // return {}; |
101 | | // } |
102 | | |
103 | | // std::optional<herald::engine::Activity> immediateSendAll(herald::engine::Activity act) override { |
104 | | // HTDBG("immediateSendAll called"); |
105 | | // return {}; |
106 | | // } |
107 | | |
108 | | ContextT& ctx; |
109 | | HLOGGER(ContextT); |
110 | | }; |
111 | | |
112 | | template <typename ContextT, typename BLEDBT> |
113 | | class MockHeraldV1ProtocolProvider : public herald::ble::HeraldProtocolV1Provider { |
114 | | public: |
115 | | MockHeraldV1ProtocolProvider(ContextT& context,BLEDBT& bledb) |
116 | | : ctx(context), db(bledb), hasIdentifiedOs(false), lastDeviceOS(), hasReadPayload(false), lastDevicePayload() |
117 | | // ,hasImmediateSend(false), lastImmediateSend(), hasImmediateSendAll(false), lastImmediateSendAll() |
118 | | HLOGGERINIT(ctx,"TESTS","MockHeraldV1ProtocolProvider") |
119 | 1 | {} |
120 | 1 | ~MockHeraldV1ProtocolProvider() = default; |
121 | | |
122 | | // FOR PLATFORMS WITH STD::ASYNC:- |
123 | | // void openConnection(const herald::datatype::TargetIdentifier& toTarget, |
124 | | // const herald::ble::HeraldConnectionCallback& connCallback) override { |
125 | | // connCallback(toTarget, true); |
126 | | // } |
127 | | // void closeConnection(const herald::datatype::TargetIdentifier& toTarget, |
128 | | // const herald::ble::HeraldConnectionCallback& connCallback) override { |
129 | | // connCallback(toTarget,false); |
130 | | // } |
131 | | |
132 | | // void serviceDiscovery(herald::engine::Activity act, herald::engine::CompletionCallback cb) override { |
133 | | // HTDBG("serviceDiscovery called"); |
134 | | // auto device = db->device(std::get<1>(act.prerequisites.front()).value()); |
135 | | // device->operatingSystem(herald::ble::BLEDeviceOperatingSystem::android); |
136 | | // hasIdentifiedOs = true; |
137 | | // lastDeviceOS = device->identifier(); |
138 | | // cb(act,{}); |
139 | | // } |
140 | | |
141 | | // void readPayload(herald::engine::Activity act, herald::engine::CompletionCallback cb) override { |
142 | | // HTDBG("readPayload called"); |
143 | | // auto device = db->device(std::get<1>(act.prerequisites.front()).value()); |
144 | | // device->payloadData(herald::datatype::Data(std::byte(0x02),2)); |
145 | | // hasReadPayload = true; |
146 | | // lastDevicePayload = device->identifier(); |
147 | | // cb(act,{}); |
148 | | // } |
149 | | |
150 | | // void immediateSend(herald::engine::Activity act, herald::engine::CompletionCallback cb) override { |
151 | | // HTDBG("immediateSend called"); |
152 | | // auto device = db->device(std::get<1>(act.prerequisites.front()).value()); |
153 | | // hasImmediateSend = true; |
154 | | // lastImmediateSend = device->identifier(); |
155 | | // device->clearImmediateSendData(); |
156 | | // cb(act,{}); |
157 | | // } |
158 | | |
159 | | // void immediateSendAll(herald::engine::Activity act, herald::engine::CompletionCallback cb) override { |
160 | | // HTDBG("immediateSendAll called"); |
161 | | // auto device = db->device(std::get<1>(act.prerequisites.front()).value()); |
162 | | // hasImmediateSendAll = true; |
163 | | // lastImmediateSendAll = device->identifier(); |
164 | | // device->clearImmediateSendData(); |
165 | | // cb(act,{}); |
166 | | // } |
167 | | |
168 | | // FOR PLATFORMS WITHOUT:- |
169 | 2 | bool openConnection(const herald::datatype::TargetIdentifier& toTarget) override { |
170 | 2 | return true; |
171 | 2 | } |
172 | 1 | bool closeConnection(const herald::datatype::TargetIdentifier& toTarget) override { |
173 | 1 | return false; |
174 | 1 | } |
175 | | |
176 | 2 | void restartScanningAndAdvertising() override {} |
177 | | |
178 | 1 | std::optional<herald::engine::Activity> serviceDiscovery(herald::engine::Activity act) override { |
179 | 1 | HTDBG("serviceDiscovery called"); |
180 | 1 | auto& device = db.device(std::get<1>(act.prerequisites.front()).value()); |
181 | 1 | std::vector<herald::datatype::UUID> heraldServiceList; |
182 | 1 | herald::ble::BLESensorConfiguration cfg; |
183 | 1 | heraldServiceList.push_back(cfg.serviceUUID); |
184 | 1 | device.services(heraldServiceList); |
185 | 1 | device.operatingSystem(herald::ble::BLEDeviceOperatingSystem::android); |
186 | 1 | hasIdentifiedOs = true; |
187 | 1 | lastDeviceOS = device.identifier(); |
188 | 1 | return {}; |
189 | 1 | } |
190 | | |
191 | 1 | std::optional<herald::engine::Activity> readPayload(herald::engine::Activity act) override { |
192 | 1 | HTDBG("readPayload called"); |
193 | 1 | auto& device = db.device(std::get<1>(act.prerequisites.front()).value()); |
194 | 1 | device.payloadData(herald::datatype::Data(std::byte(0x02),2)); |
195 | 1 | hasReadPayload = true; |
196 | 1 | lastDevicePayload = device.identifier(); |
197 | 1 | return {}; |
198 | 1 | } |
199 | | |
200 | | // std::optional<herald::engine::Activity> immediateSend(herald::engine::Activity act) override { |
201 | | // HTDBG("immediateSend called"); |
202 | | // auto& device = db.device(std::get<1>(act.prerequisites.front()).value()); |
203 | | // hasImmediateSend = true; |
204 | | // lastImmediateSend = device.identifier(); |
205 | | // device.clearImmediateSendData(); |
206 | | // return {}; |
207 | | // } |
208 | | |
209 | | // std::optional<herald::engine::Activity> immediateSendAll(herald::engine::Activity act) override { |
210 | | // HTDBG("immediateSendAll called"); |
211 | | // auto& device = db.device(std::get<1>(act.prerequisites.front()).value()); |
212 | | // hasImmediateSendAll = true; |
213 | | // lastImmediateSendAll = device.identifier(); |
214 | | // device.clearImmediateSendData(); |
215 | | // return {}; |
216 | | // } |
217 | | |
218 | | ContextT& ctx; |
219 | | BLEDBT& db; |
220 | | |
221 | | bool hasIdentifiedOs; |
222 | | std::optional<herald::datatype::TargetIdentifier> lastDeviceOS; |
223 | | |
224 | | bool hasReadPayload; |
225 | | std::optional<herald::datatype::TargetIdentifier> lastDevicePayload; |
226 | | |
227 | | // bool hasImmediateSend; |
228 | | // std::optional<herald::datatype::TargetIdentifier> lastImmediateSend; |
229 | | |
230 | | // bool hasImmediateSendAll; |
231 | | // std::optional<herald::datatype::TargetIdentifier> lastImmediateSendAll; |
232 | | |
233 | | HLOGGER(ContextT); |
234 | | }; |
235 | | |
236 | | |
237 | | |
238 | | |
239 | 1 | TEST_CASE("coordinator-complex-iterations", "[coordinator][iterations][complex]") { |
240 | 1 | // create our BLE coordinator |
241 | 1 | DummyLoggingSink dls; |
242 | 1 | DummyBluetoothStateManager dbsm; |
243 | 1 | herald::DefaultPlatformType dpt; |
244 | 1 | herald::Context ctx(dpt,dls,dbsm); // default context include |
245 | 1 | auto serviceUUID = herald::datatype::UUID::fromString("428132af-4746-42d3-801e-4572d65bfd9b"); |
246 | 1 | // INFO("Service UUID " << std::string(serviceUUID)); |
247 | 1 | REQUIRE(ctx.getSensorConfiguration().serviceUUID == serviceUUID); |
248 | 1 | auto blankUUID = herald::datatype::UUID::fromString(""); |
249 | 1 | // INFO("Blank UUID " << std::string(blankUUID)); |
250 | 1 | REQUIRE(ctx.getSensorConfiguration().serviceUUID != blankUUID); |
251 | 1 | using CT = typename herald::Context<herald::DefaultPlatformType,DummyLoggingSink,DummyBluetoothStateManager>; |
252 | 1 | herald::ble::ConcreteBLEDatabase db(ctx); |
253 | 1 | MockHeraldV1ProtocolProvider pp(ctx,db); |
254 | 1 | herald::ble::HeraldProtocolBLECoordinationProvider coord(ctx,db,pp); |
255 | 1 | using CPT = herald::ble::HeraldProtocolBLECoordinationProvider< |
256 | 1 | CT, |
257 | 1 | herald::ble::ConcreteBLEDatabase<CT>, |
258 | 1 | MockHeraldV1ProtocolProvider<CT,herald::ble::ConcreteBLEDatabase<CT>> |
259 | 1 | >; |
260 | 1 | |
261 | 1 | // Mock Sensor |
262 | 1 | MockSensor<CPT> mockSensor(coord); |
263 | 1 | |
264 | 1 | // register ble coordinator |
265 | 1 | herald::engine::Coordinator<CT> c(ctx); |
266 | 1 | c.add(mockSensor); // registers the BLE coordinator |
267 | 1 | c.start(); |
268 | 1 | |
269 | 1 | // section wide data definitions |
270 | 1 | herald::datatype::Data devMac1(std::byte(0x1d),6); |
271 | 1 | herald::datatype::TargetIdentifier device1(devMac1); |
272 | 1 | |
273 | 1 | herald::datatype::Data devMac2(std::byte(0x1f),6); |
274 | 1 | herald::datatype::TargetIdentifier device2(devMac2); |
275 | 1 | |
276 | 1 | herald::datatype::Data devMac3(std::byte(0x09),6); |
277 | 1 | herald::datatype::TargetIdentifier device3(devMac3); |
278 | 1 | |
279 | 1 | SECTION("blecoordinator-complex-iterations-01-device1") { |
280 | 1 | herald::ble::BLEDevice& devPtr1 = db.device(device1); |
281 | 1 | |
282 | 1 | // Now perform one iteration |
283 | 1 | c.iteration(); // should call serviceDiscovery |
284 | 1 | |
285 | 1 | // check provider used |
286 | 1 | REQUIRE(pp.hasIdentifiedOs == true); |
287 | 1 | REQUIRE(pp.lastDeviceOS == device1); |
288 | 1 | REQUIRE(pp.hasReadPayload == false); |
289 | 1 | // REQUIRE(pp.hasImmediateSend == false); |
290 | 1 | // REQUIRE(pp.hasImmediateSendAll == false); |
291 | 1 | |
292 | 1 | // second iteration should read payload |
293 | 1 | c.iteration(); |
294 | 1 | REQUIRE(pp.hasIdentifiedOs == true); |
295 | 1 | REQUIRE(pp.lastDeviceOS == device1); |
296 | 1 | REQUIRE(pp.hasReadPayload == true); |
297 | 1 | REQUIRE(pp.lastDevicePayload == device1); |
298 | 1 | // REQUIRE(pp.hasImmediateSend == false); |
299 | 1 | // REQUIRE(pp.hasImmediateSendAll == false); |
300 | 1 | |
301 | 1 | // TODO MARK DEVICE FOR IMMEDIATE SEND IN PROVIDER |
302 | 1 | // devPtr1.immediateSendData(herald::datatype::Data(std::byte(0x09),4)); |
303 | 1 | |
304 | 1 | // Now perform one iteration |
305 | 1 | c.iteration(); |
306 | 1 | |
307 | 1 | // check provider used |
308 | 1 | REQUIRE(pp.hasIdentifiedOs == true); |
309 | 1 | REQUIRE(pp.lastDeviceOS == device1); |
310 | 1 | REQUIRE(pp.hasReadPayload == true); |
311 | 1 | REQUIRE(pp.lastDevicePayload == device1); |
312 | 1 | // REQUIRE(pp.hasImmediateSend == true); |
313 | 1 | // REQUIRE(pp.lastImmediateSend == device1); |
314 | 1 | // REQUIRE(pp.hasImmediateSendAll == false); |
315 | 1 | |
316 | 1 | // Now perform one iteration |
317 | 1 | c.iteration(); |
318 | 1 | |
319 | 1 | // check provider used |
320 | 1 | REQUIRE(pp.hasIdentifiedOs == true); |
321 | 1 | REQUIRE(pp.lastDeviceOS == device1); |
322 | 1 | REQUIRE(pp.hasReadPayload == true); |
323 | 1 | REQUIRE(pp.lastDevicePayload == device1); |
324 | 1 | // REQUIRE(pp.hasImmediateSend == true); |
325 | 1 | // REQUIRE(pp.lastImmediateSend == device1); |
326 | 1 | // REQUIRE(pp.hasImmediateSendAll == false); |
327 | 1 | } |
328 | 1 | |
329 | 1 | c.stop(); |
330 | 1 | } |